package web.controller.my;

import com.github.pagehelper.PageInfo;
import framework.config.SecurityConfig;
import framework.config.UserConfig;
import framework.crypto.GeneralCrypto;
import framework.exceptions.Error401Exception;
import framework.security.AuthService;
import framework.security.token.AuthTokenBuilder;
import framework.security.token.AuthTokenInfo;
import framework.utils.ErrorUtil;
import framework.vo.ResultInfo;
import framework.vo.ResultList;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import system.entity.SysFunc;
import system.entity.SysUser;
import system.entity.SysUserEvent;
import system.service.sys.SysFuncService;
import system.service.sys.SysUserEventService;
import system.service.sys.SysUserService;
import web.vo.AuthInfo;
import web.vo.MenuOption;
import web.vo.TokenInfo;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/my")
@Api(tags = "个人信息")
public class MyController {

    @Autowired
    private AuthService authService;
    @Autowired
    private UserConfig userConfig;
    @Autowired
    private SysUserEventService userEventService;
    @Autowired
    private SysUserService userService;
    @Autowired
    private SysFuncService funcService;
    @Autowired
    private GeneralCrypto generalCrypto;
    @Autowired
    private AuthTokenBuilder authTokenBuilder;
    @Autowired
    private SecurityConfig securityConfig;

    @ApiOperation("账号信息")
    @GetMapping("/profile")
    public ResultInfo<SysUser> profile() {
        Long accountId = this.authService.getAccountId();
        SysUser info = userService.loadById(accountId);
        return new ResultInfo<>(info);
    }

    @ApiOperation("账号信息")
    @PostMapping("/profile")
    public ResultInfo<Integer> profileSave(SysUser param) {
        Long id = authService.getAccountId();
        Date now = new Date();
        param.setId(id);
        param.setUpdateTime(now);
        //
        Integer updated = userService.updateProfile(param);
        ResultInfo<Integer> info = new ResultInfo<>(updated);
        return info;
    }

    @ApiOperation("密码修改")
    @PostMapping("/password")
    public ResultInfo<Integer> edit(@RequestParam String oldPassword, @RequestParam String password) {
        if (!authService.isAuthenticated())
            ErrorUtil.noAccess();
        //
        if (this.generalCrypto.enable()) {
            oldPassword = this.generalCrypto.decryptFromBase64AsString(oldPassword);
            password = this.generalCrypto.decryptFromBase64AsString(password);
        }
        //
        int updated = 0;
        updated += userService.updatePassword(authService.getAccountId(), oldPassword, password);
        ResultInfo<Integer> info = new ResultInfo<>(updated);
        return info;
    }

    @ApiOperation("账户事件列表")
    @GetMapping("/event/list")
    public ResultList<SysUserEvent> list(SysUserEvent param, @RequestParam(value = "pageIndex", defaultValue = "1") Integer pageIndex, @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        long loginUserId = authService.getAccountId();
        param.setUserId(loginUserId);
        PageInfo<SysUserEvent> info = userEventService.list(param, pageIndex, pageSize);
        return new ResultList<>(info);
    }

    /**
     * 获取我的功能列表(菜单列表)
     *
     * @return
     */
    @ApiOperation("我的菜单")
    @GetMapping("/menu")
    public ResultInfo<AuthInfo> menu() {
        long userId = authService.getAccountId();
        List<String> permissions = new ArrayList<>(this.userService.loadUserPermissions(userId));
        List<SysFunc> funcList = new ArrayList<>(this.funcService.loadUserFunc(userId));
        MenuOption.cleanNoPermission(permissions, funcList);
        List<MenuOption> menuOptions = MenuOption.tree(funcList, true);
        return new ResultInfo<>(new AuthInfo(menuOptions, permissions));
    }

    /**
     * TOKEN刷新
     *
     * @return
     */
    @GetMapping("/token")
    public ResultInfo<TokenInfo> token(HttpServletResponse response, @RequestParam(required = false) Integer seconds) throws IOException {
        long accountId = this.authService.getAccountId();
        if (accountId == 0)
            throw new Error401Exception("No auth");
        Integer tokenSeconds;
        if (seconds != null && seconds > 0) {
            tokenSeconds = seconds;
        } else {
            tokenSeconds = securityConfig.getTokenSeconds();
        }
        if (tokenSeconds == null) {
            throw new RemoteException("No set sys.security.token-seconds or not input seconds in application configuration file");
        }
        // 获取会话标识
        long sid = this.authService.getSid();
        AuthTokenInfo tokenInfo = new AuthTokenInfo(accountId, new Date(new Date().getTime() + tokenSeconds * 1000), tokenSeconds, sid);
        String token = authTokenBuilder.encode(tokenInfo);
        return new ResultInfo<>(new TokenInfo(accountId, token, tokenSeconds));
    }

}